<template>
	<view class="apple-pay-page">
		<u-loading-page :loading="true" :loading-text="loadingText" icon-size="100rpx" font-size="34rpx" color="#000"
			bg-color="#f1f2f6" loadingColor="#3476FE"></u-loading-page>
		<u-modal :show="showModal" @confirm="confirmCompletePay" @cancel="cancelCompletePay" ref="uModal"
			:asyncClose="true" :showCancelButton="true" title="确认支付" confirmText="已支付" cancelText="未支付">
			请确认您的支付状态，避免订单丢失，支付完成前请不要关闭！
		</u-modal>
	</view>
</template>

<script>
	const IapTransactionState = {
		purchasing: "0", // A transaction that is being processed by the App Store.
		purchased: "1", // A successfully processed transaction.
		failed: "2", // A failed transaction.
		restored: "3", // A transaction that restores content previously purchased by the user.
		deferred: "4" // A transaction that is in the queue, but its final status is pending external action such as Ask to Buy.
	};

	class Iap {

		_channel = null;
		_channelError = null;
		_productIds = [];

		_ready = false;

		constructor({
			products
		}) {
			this._productIds = products;
		}

		init() {
			return new Promise((resolve, reject) => {
				this.getChannels((channel) => {
					this._ready = true;
					resolve(channel);
				}, (err) => {
					reject(err);
				})
			})
		}

		getProduct(productIds) {
			return new Promise((resolve, reject) => {
				this._channel.requestProduct(productIds || this._productIds, (res) => {
					resolve(res);
				}, (err) => {
					reject(err);
				})
			});
		}

		requestPayment(orderInfo) {
			return new Promise((resolve, reject) => {
				uni.requestPayment({
					provider: 'appleiap',
					orderInfo: orderInfo,
					success: (res) => {
						resolve(res);
					},
					fail: (err) => {
						reject(err);
					},
					complete: () => {
						console.log('requestPayment appleiap 完成')
					}
				});
			});
		}

		restoreCompletedTransactions(username) {
			return new Promise((resolve, reject) => {
				this._channel.restoreCompletedTransactions({
					manualFinishTransaction: true,
					username: username || ''
				}, (res) => {
					resolve(res);
				}, (err) => {
					reject(err);
				})
			});
		}

		finishTransaction(transaction) {
			return new Promise((resolve, reject) => {
				this._channel.finishTransaction(transaction, (res) => {
					resolve(res);
				}, (err) => {
					reject(err);
				});
			});
		}

		getChannels(success, fail) {
			if (this._channel !== null) {
				success(this._channel)
				return
			}

			if (this._channelError !== null) {
				fail(this._channelError)
				return
			}

			uni.getProvider({
				service: 'payment',
				success: (res) => {
					this._channel = res.providers.find((channel) => {
						return (channel.id === 'appleiap')
					})

					if (this._channel) {
						success(this._channel)
					} else {
						this._channelError = {
							errMsg: 'paymentContext:fail iap service not found'
						}
						fail(this._channelError)
					}
				}
			});
		}

		get channel() {
			return this._channel;
		}

		get ready() {
			return this._ready;
		}
	}

	export default {
		data() {
			return {
				loadingText: '检测支付环境...',
				loading: false,
				showModal: false,
				_iap: null,
				productId: '',
				outTradeNo: '',
				notifyUrl: '',
			};
		},
		onLoad: function(option) {
			const p = JSON.parse(option.p || "{}") || {};
			console.log('apple iap 参数', p)
			this.productId = `${p.productId}`;
			this.outTradeNo = p.outTradeNo;
			this.notifyUrl = p.notifyUrl;

			// #ifdef APP-PLUS
			this._iap = new Iap({
				products: [p.productId] // 苹果开发者中心创建
			})

			this.init();
			// #endif

			this.timer = setTimeout(() => {
				this.showModal = true;
				this.timer = null;
			}, 1000 * 60);
		},
		onShow() {},
		onUnload() {
			if (this.timer) {
				clearTimeout(this.timer)
			}
		},
		methods: {
			init() {
				this.loadingText = '检测支付环境...';

				//初始化， 获取iap支付通道
				this._iap.init().then(async () => {
					if (this._iap.ready === true) {

						//检测已支付且未关闭的订单
						await this.restore();

console.log(this.productId,111111)
						//查询产品列表
						this._iap.getProduct([this.productId]).then(products => {
							console.log("查询产品列表", products)
							//支付
							this.payment().then(() => {
								uni.redirectTo({
									url: '/pages/views/packageB/Publicdocuments/paysuccess'
								})
							}).catch(() => {
								this.showModal = true;
								if (this.timer) {
									clearTimeout(this.timer)
								}
							})
						}).catch(err => {
							console.log("查询产品列表失败", err)
							this.loadingText = '购买产品不存在';
						})


					}

				}).catch(() => {
					uni.showModal({
						title: "检测支付环境",
						content: e.message,
						showCancel: false
					});

					uni.redirectTo({
						url: '/pages/views/packageB/Publicdocuments/payfailure'
					})
				})
			},
			async restore() {
				// 检查上次用户已支付且未关闭的订单，可能出现原因：首次绑卡，网络中断等异常

				// 在此处检查用户是否登陆

				this.loadingText = '正在检测已支付且未关闭的订单...';
				console.log("正在检测已支付且未关闭的订单")

				// 从苹果服务器检查未关闭的订单，可选根据 username 过滤，和调用支付时透传的值一致
				const transactions = await this._iap.restoreCompletedTransactions().catch(err => {
					console.log('查询未关闭的订单异常', err)
				});
				if (!transactions || !transactions.length) {
					console.log('没有查询到未关闭的订单')
					return;
				}
				console.log('查询到未关闭的订单', transactions)

				// 开发者业务逻辑，从服务器获取当前用户未完成的订单列表，和本地的比较
				// 此处省略

				transactions.forEach(async transaction => {
					const payment = transaction.payment;
					switch (transaction.transactionState) {
						case IapTransactionState.purchased:
							// 用户已付款，在此处请求开发者服务器，在服务器端请求苹果服务器验证票据
							const isValidateSuccess = await this.validatePaymentResult({
								outTradeNo: payment.username,
								transactionReceipt: transaction
									.transactionReceipt, // 不可作为订单唯一标识
								transactionIdentifier: transaction
									.transactionIdentifier
							})
							if (isValidateSuccess) {
								// 验证通过，交易结束，关闭订单
								await this._iap.finishTransaction(transaction).catch(err => {
									console.log("关闭订单异常", err)
								});
							} else {
								console.log('服务器验证票据失败')
							}

							break;
						case IapTransactionState.failed:
							// 关闭未支付的订单
							await this._iap.finishTransaction(transaction).catch(err => {
								console.log("关闭订单异常", err)
							});
							break;
						default:
							break;
					}

				})
			},
			payment() {
				if (this.loading == true) {
					return;
				}
				this.loading = true;

				this.loadingText = '支付处理中，耐心等待...';

				console.log("调起支付 支付处理中...")
				return new Promise((resolve, reject) => {
					// 请求苹果支付
					this._iap.requestPayment({
						productid: this.productId,
						username: this.outTradeNo, //根据业务需求透传参数，关联用户和订单关系
						manualFinishTransaction: true,
					}).then(async transaction => {
						this.loadingText = '支付成功...';
						// 在此处请求开发者服务器，在服务器端请求苹果服务器验证票据
						console.log('调起支付 成功', transaction)
						const isValidateSuccess = await this.validatePaymentResult({
							outTradeNo: this.outTradeNo,
							transactionReceipt: transaction.transactionReceipt, // 不可作为订单唯一标识
							transactionIdentifier: transaction.transactionIdentifier
						})
						console.log("验证",isValidateSuccess);
						if (isValidateSuccess) {
							console.log('服务器验证票据成功 关闭订单')
							// 验证成功后关闭订单
							await this._iap.finishTransaction(transaction).catch(err => {
								console.log("关闭订单异常", err)
							});

							resolve();
						} else {
							console.log('服务器验证票据失败')
							reject()
						}

					}).catch(err => {
						console.log('调起支付 失败', err)
						// uni.showModal({
						// 	title: "调起支付失败",
						// 	content: err.errMsg,
						// 	showCancel: false
						// });
						reject()
					}).finally(() => {
						this.loading = false;
					});
				})
			},
			validatePaymentResult(data) {
				console.log('验证参数', data)
				return new Promise((resolve, reject) => {
					uni.request({
						url: this.notifyUrl,
						method: "POST",
						header: {
							'Content-Type': 'application/json',
						},
						data: data,
						success: (res) => {
							if (res.data == 'success') {
								resolve(true);
							} else {
								resolve(false);
							}
						},
						fail(res) {
							resolve(false);
						},
					});
				});
			},
			async confirmCompletePay() {
				// #ifdef APP-PLUS
				//检测已支付且未关闭的订单
				await this.restore();
				// #endif
				this.showModal = false;
				uni.redirectTo({
					url: '/pages/views/packageB/Publicdocuments/paysuccess'
				})
			},
			async cancelCompletePay() {
				this.showModal = false;
				uni.redirectTo({
					url: '/pages/views/packageB/Publicdocuments/payfailure'
				})
			}
		}
	}
</script>

<style lang="scss" scoped>
	.apple-pay-page {
		height: 100vh;
		height: 100vh;
		display: flex;
		align-items: center;
		justify-content: center;
	}
</style>